package io.nutz.nutzsite.common.base;

import io.nutz.nutzsite.common.page.TableDataInfo;
import io.nutz.nutzsite.common.utils.StringUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;

import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Condition;
import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.QueryResult;
import org.nutz.dao.Sqls;
import org.nutz.dao.entity.MappingField;
import org.nutz.dao.pager.Pager;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.sql.SqlCallback;
import org.nutz.dao.util.Daos;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.service.EntityService;

/**
 * @author Hamming_Yu on 2018/12/31.
 */
public class Service<T> extends EntityService<T> {
    protected final static int DEFAULT_PAGE_NUMBER = 10;

    public Service() {
        super();
    }

    public Service(Dao dao) {
        super(dao);
    }


    /**
     * 统计符合条件的对象表条数
     *
     * @param cnd
     * @return
     */
    @Override
    public int count(Condition cnd) {
        return this.dao().count(this.getEntityClass(), cnd);
    }

    /**
     * 统计对象表条数
     *
     * @return
     */
    @Override
    public int count() {
        return this.dao().count(this.getEntityClass());
    }

    /**
     * 统计符合条件的记录条数
     *
     * @param tableName
     * @param cnd
     * @return
     */
    public int count(String tableName, Condition cnd) {
        return this.dao().count(tableName, cnd);
    }

    /**
     * 统计表记录条数
     *
     * @param tableName
     * @return
     */
    public int count(String tableName) {
        return this.dao().count(tableName);
    }

    public T fetch(long id) {
        return this.dao().fetch(this.getEntityClass(), id);
    }

    public T fetch(String name) {
        return this.dao().fetch(this.getEntityClass(), name);
    }
    public T fetch(Condition cnd) {
        return this.dao().fetch(this.getEntityClass(), cnd);
    }
    /**
     * 获取主表主键映射的从表对象
     * @param t
     * @param name
     * @return
     */
    public T fetchLinks(T t, String name) {
        return this.dao().fetchLinks(t, name);
    }
    /**
     * 获取主表主键映射的从表多对象
     * @param t
     * @param name
     * @return
     */
    public List<T> fetchLinks(List<T> t, String name) {
        return this.dao().fetchLinks(t, name);
    }

    public T fetchLinks(T t, String name, Condition cnd) {
        return this.dao().fetchLinks(t, name, cnd);
    }

    public T insert(T t) {
        return this.dao().insert(t);
    }
    
    public List<T> insert(List<T> t) {
        return this.dao().insert(t);
    }

    public void insert(String tableName, Chain chain) {
        this.dao().insert(tableName, chain);
    }
    /**
     * 可以一次将  一条主表记录 以及它对应的 多条从表记录 一起插入到数据表中
     * @param t
     * @param slave
     * @return
     */
    public T insertWith(T t, String slave) {
        return this.dao().insertWith(t, slave);
    }
    /**
     * 一条 SQL ,通过batch插入多条记录
     * @param t
     * @return
     */
    public T fastInsert(T t) {
        return this.dao().fastInsert(t);
    }

    /**
     * 更新
     * @param obj
     * @return
     */
    public int update(Object obj) {
        return this.dao().update(obj);
    }

    /**
     * 忽略值为null的字段
     *
     * @param obj
     * @return
     */
    public int updateIgnoreNull(Object obj) {
        return this.dao().updateIgnoreNull(obj);
    }

    /**
     * 部分更新实体表
     *
     * @param chain
     * @param cnd
     * @return
     */
    @Override
    public int update(Chain chain, Condition cnd) {
        return this.dao().update(this.getEntityClass(), chain, cnd);
    }

    /**
     * 部分更新表
     *
     * @param tableName
     * @param chain
     * @param cnd
     * @return
     */
    public int update(String tableName, Chain chain, Condition cnd) {
        return this.dao().update(tableName, chain, cnd);
    }


    public int delete(long id) {
        return this.dao().delete(this.getEntityClass(), id);
    }

    public int delete(int id) {
        return this.dao().delete(this.getEntityClass(), id);
    }

    public int delete(String name) {
        return this.dao().delete(this.getEntityClass(), name);
    }

    /**
     * 批量删除
     *
     * @param ids
     */
    public void delete(Integer[] ids) {
        this.dao().clear(getEntityClass(), Cnd.where("id", "in", ids));
    }

    /**
     * 批量删除
     *
     * @param ids
     */
    public void delete(Long[] ids) {
        this.dao().clear(getEntityClass(), Cnd.where("id", "in", ids));
    }

    /**
     * 批量删除
     *
     * @param ids
     */
    public void delete(String[] ids) {
        this.dao().clear(getEntityClass(), Cnd.where("id", "in", ids));
    }
/**
 * 按条件删除
 * @param cnd
 */
    public void delete(Cnd cnd) {
        this.dao().clear(getEntityClass(), cnd);
    }
    /**
     * 伪删除
     *
     * @param id
     * @return
     */
    public int vDelete(String id) {
        return this.dao().update(this.getEntityClass(), Chain.make("delFlag", true), Cnd.where("id", "=", id));
    }

    /**
     * 批量伪删除
     *
     * @param ids
     * @return
     */
    public int vDelete(String[] ids) {
        return this.dao().update(this.getEntityClass(), Chain.make("delFlag", true), Cnd.where("id", "in", ids));
    }

    public List<T> query(int pageNumber, int pageSize, Cnd cnd) {
        Pager pager = this.dao().createPager(pageNumber, pageSize);
        List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
        return list;
    }

    public List<T> query(Condition cnd, int pageNumber, int pageSize){
        Pager pager = this.dao().createPager(pageNumber, pageSize);
        List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
        return list;
    }
    /**
     * 关联查询 分页
     *
     * @param pageNumber
     * @param pageSize
     * @param cnd
     * @param linkname
     * @return
     */
    public List<T> queryByJoin(int pageNumber, int pageSize, Cnd cnd, String linkname) {
        Pager pager = this.dao().createPager(pageNumber, pageSize);
        List<T> list = this.dao().queryByJoin(this.getEntityClass(), linkname, cnd, pager);
        return list;
    }
    /**
     * 关联查询 无分页
     *
     * @param pageNumber
     * @param pageSize
     * @param cnd
     * @param linkname
     * @return
     */
    public List<T> queryByJoin( Cnd cnd, String linkname) {
        List<T> list = this.dao().queryByJoin(this.getEntityClass(), linkname, cnd, null);
        return list;
    }

    /**
     * 通过LONG主键获取部分字段值
     *
     * @param fieldName
     * @param id
     * @return
     */
    public T getField(String fieldName, long id) {
        return Daos.ext(this.dao(), FieldFilter.create(this.getEntityClass(), fieldName))
                .fetch(this.getEntityClass(), id);
    }

    /**
     * 通过INT主键获取部分字段值
     *
     * @param fieldName
     * @param id
     * @return
     */
    public T getField(String fieldName, int id) {
        return Daos.ext(this.dao(), FieldFilter.create(this.getEntityClass(), fieldName))
                .fetch(this.getEntityClass(), id);
    }


    /**
     * 通过NAME主键获取部分字段值
     *
     * @param fieldName 支持通配符 ^(a|b)$
     * @param name
     * @return
     */
    public T getField(String fieldName, String name) {
        return Daos.ext(this.dao(), FieldFilter.create(this.getEntityClass(), fieldName))
                .fetch(this.getEntityClass(), name);
    }

    /**
     * 通过条件获取部分字段值
     *
     * @param fieldName 支持通配符 ^(a|b)$
     * @param cnd
     * @return
     */
    public T getField(String fieldName, Condition cnd) {
        return Daos.ext(this.dao(), FieldFilter.create(this.getEntityClass(), fieldName))
                .fetch(this.getEntityClass(), cnd);
    }
    /**
     * 查询获取部分字段
     *
     * @param fieldName 支持通配符 ^(a|b)$
     * @param cnd
     * @return
     */
    public List<T> query(String fieldName, Condition cnd) {
        return Daos.ext(this.dao(), FieldFilter.create(this.getEntityClass(), fieldName))
                .query(this.getEntityClass(), cnd);
    }
    public String queryRoleUser(String roles){
		return StringUtils.getSeqRowValue2(this.dao(),Sqls.create("select user_id from sys_user_role where role_id in "+StringUtils.StringToString2(roles)));
    }
    /**
     * 默认页码
     *
     * @param pageNumber
     * @return
     */
    protected int getPageNumber(Integer pageNumber) {
        return Lang.isEmpty(pageNumber) ? 1 : pageNumber;
    }

    /**
     * 默认页大小
     *
     * @param pageSize
     * @return
     */
    protected int getPageSize(int pageSize) {
        return pageSize == 0 ? DEFAULT_PAGE_NUMBER : pageSize;
    }


    /**
     * 分页查询
     * @param pageNumber
     * @param pageSize
     * @return
     */
    public QueryResult listPage( int pageNumber, int pageSize){
        Pager pager = this.dao().createPager(pageNumber, pageSize);
        List<T> list = this.dao().query(this.getEntityClass(), null, pager);
        pager.setRecordCount(this.dao().count(this.getEntityClass()));
        return new QueryResult(list, pager);
    }

    
    /**
     * 分页查询
     * @param pageNumber
     * @param pageSize
     * @param cnd
     * @return
     */
    public QueryResult listPage( int pageNumber, int pageSize,Condition cnd){
        Pager pager = this.dao().createPager(pageNumber, pageSize);
        List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
        pager.setRecordCount(this.dao().count(getEntityClass(), cnd));
        return new QueryResult(list, pager);
    }
   
/**
 * 关联排序查询
 * @param pageNumber
 * @param pageSize
 * @param cnd
 * @param orderByColumn
 * @param isAsc
 * @param linkname
 * @return
 */
    public QueryResult listPage(int pageNumber, int pageSize, Cnd cnd, String orderByColumn, String isAsc, String linkname) {
        Pager pager = this.dao().createPager(pageNumber, pageSize);
        if (Strings.isNotBlank(orderByColumn) && Strings.isNotBlank(isAsc)) {
            MappingField field = dao().getEntity(this.getEntityClass()).getField(orderByColumn);
            if (Lang.isNotEmpty(field)) {
                cnd.orderBy(field.getColumnName(), isAsc);
            }
        }
        if (Strings.isBlank(linkname)) {
            List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
            pager.setRecordCount(this.dao().count(getEntityClass(), cnd));
            return new QueryResult(list, pager);
        } else {
            List<T> list = this.dao().queryByJoin(this.getEntityClass(), linkname, cnd, pager);
            pager.setRecordCount(this.dao().count(getEntityClass(), cnd));
            return new QueryResult(list, pager);
        }
    }
    /**
     * 分页关联字段查询(支持关联条件)
     *
     * @param cnd      查询条件
     * @param linkName 关联字段，支持正则 ^(a|b)$
     * @param linkCnd  关联条件
     * @param pager    分页对象
     * @return
     */
    public List<T> query(Condition cnd, String linkName, Condition linkCnd, Pager pager) {
        List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
        if (!Strings.isBlank(linkName)) {
            this.dao().fetchLinks(list, linkName, linkCnd);
        }
        return list;
    }
    /**
     * 分页查询数据封装
     * @param pageNumber
     * @param pageSize
     * @return
     */
    public TableDataInfo tableList(Integer pageNumber, Integer pageSize){
        Pager pager=null;
        if(Lang.isNotEmpty(pageNumber) && Lang.isNotEmpty(pageSize)){
            pager = this.dao().createPager(pageNumber, pageSize);
        }
        List<T> list = this.dao().query(this.getEntityClass(), null, pager);
        return new TableDataInfo(list, this.dao().count(this.getEntityClass()));
    }

    /**
     * 分页查询数据封装
     * @param pageNumber
     * @param pageSize
     * @param cnd
     * @return
     */
    public TableDataInfo tableList(Integer pageNumber, Integer pageSize,Cnd cnd){
        Pager pager=null;
        if(Lang.isNotEmpty(pageNumber) && Lang.isNotEmpty(pageSize)){
            pager = this.dao().createPager(pageNumber, pageSize);
        }
        List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
        return new TableDataInfo(list, this.dao().count(this.getEntityClass(),cnd));
    }

    /**
     * 分页查询数据封装 查询关联数据
     *
     * @param pageNumber
     * @param pageSize
     * @param cnd
     * @param linkname
     * @return
     */
    public TableDataInfo tableList(Integer pageNumber, Integer pageSize, Cnd cnd, String orderByColumn, String isAsc, String linkname) {
        Pager pager=null;
        if(Lang.isNotEmpty(pageNumber) && Lang.isNotEmpty(pageSize)){
            pager = this.dao().createPager(pageNumber, pageSize);
        }
        if (Strings.isNotBlank(orderByColumn) && Strings.isNotBlank(isAsc)) {
            MappingField field = dao().getEntity(this.getEntityClass()).getField(orderByColumn);
            if (Lang.isNotEmpty(field)) {
                cnd.orderBy(field.getColumnName(), isAsc);
            }
        }
        if (Strings.isBlank(linkname)) {
            List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
            return new TableDataInfo(list, this.dao().count(this.getEntityClass(), cnd));
        } else {
            List<T> list = this.dao().queryByJoin(this.getEntityClass(), linkname, cnd, pager);
            return new TableDataInfo(list, this.dao().count(this.getEntityClass(), cnd));
        }
    }


    public TableDataInfo tableListFetchLinks(Integer pageNumber, Integer pageSize,Cnd cnd,String orderByColumn,String isAsc,String linkname){
        Pager pager=null;
        if(Lang.isNotEmpty(pageNumber) && Lang.isNotEmpty(pageSize)){
            pager = this.dao().createPager(pageNumber, pageSize);
        }
        if (Strings.isNotBlank(orderByColumn) && Strings.isNotBlank(isAsc)) {
            MappingField field =dao().getEntity(this.getEntityClass()).getField(orderByColumn);
            if(Lang.isNotEmpty(field)){
                cnd.orderBy(field.getColumnName(),isAsc);
            }
        }
        List<T> list = this.dao().query(this.getEntityClass(), cnd, pager);
        if (!Strings.isBlank(linkname)) {
            this.dao().fetchLinks(list, linkname);
        }
        return new TableDataInfo(list, this.dao().count(this.getEntityClass(),cnd));
    }
    /**
     * 记录列表
     * @param cnd
     * @return
     */
    
    public List<T> findList( Cnd cnd) {
        List<T> list = this.dao().query(this.getEntityClass(), cnd);
        return list;
    }
	/**
	 * 根据自定义条件查询满足条件的单个字段的字符串列表，如distinct xxx
	 *
	 * @param dao
	 * @param sql
	 * @return
	 */
	public <T> List<String> getStrRowValues( Sql sql) {
		sql.setCallback(new SqlCallback() {
			@Override
			public Object invoke(Connection conn, ResultSet rs, Sql sql)
					throws SQLException {
				List<String> list = new LinkedList<String>();
				String value = "";
				while (rs.next()) {
					value = Strings.sNull(rs.getString(1));
					list.add(value);
				}
				return list;
			}
		});
		this.dao().execute(sql);
		return sql.getList(String.class);

	}
}
